﻿#pragma once

#include "ais_context.h"
#include "kernel/kerstr.h"

namespace CAGD
{

/**
 * 颜色通道.
 */
using RGB = BPntf;
using RGBA = TCoordN<4, float, CoordsType::Pnt>;

/**
 * 可交互类型.
 * 为了便于转换为 unsigned int，不加 class
 */
enum AIS_Type
{
    BASE,
    BOX,
    POINT,
    POINTCLOUD,
    VECTOR,
    VECTORCLOUD,
    CURVE,
    MESH,
    SURFACE,
    POLE,
    POINTLIGHT,
    DIRLIGHT,
    SPOTLIGHT,
    CAMERA,
    FRAME,
    TEXT // TEXT 只用于绘制文字，没有交互对象
};

/**
 * 物体状态.
 */
enum class AIS_Status
{
    NONE,
    HANG,
    TOUCH,
    HIDDEN,
    DEAD
};

/**
 * @brief 命令状态类
 *
 */
enum class CmdStatus
{
    KEEP,     // 正在运行
    STEP,     // 执行一步
    MOVE,     // 鼠标移动
    PERFORM,  // 完成执行
    TERMINATE // 中断
};

/**
 * 消息类型.
 */
enum class Message
{
    // 全局命令
    SHOW,
    HIDE,
    DEAD,
    MOVE_PARENT,
    MOVE_CHILD,
    SELECT,
    RELEASE,

    // 特殊命令
    NONE,
    SCALE,
    SHOW_CTRL,
    HIDE_CTRL,
    SHOW_INFO,
    HIDE_INFO
};

/**
 * 纹理类型.
 * 为了便于转换为 unsigned int，不加 class
 */
enum TEXTURE
{
    YELLOW2D,
    WHITE2D,
    RED2D,
    GREEN2D,
    BLUE2D,
    BLACK2D,
    CHESS,
    DASH,
    SNIPPLE,
    BACKGROUND
};

/**
 * @brief 光照结构.
 * @param color
 * @see
 */
struct Light
{
    BPntf position;
    BVecf direction;

    BPntf ambient;
    BPntf diffuse;
    BPntf specular;

    float cutOff;
};

/**
 * AIS_Info 记录交互信息.
 */
struct AIS_Info
{
    AIS_Status status;            // 物体状态
    unsigned int index;           // 索引标记
    unsigned int size;            // 绘制数量
    unsigned int psize;           // 点的大小
    unsigned int diffuseTex;      // 散射纹理
    unsigned int specularTex;     // 镜面纹理
    unsigned int reflectTex;      // 反射纹理
    unsigned int reflactTex;      // 折射纹理
    double depth;                 // 深度
    bool smooth;                  // 是否 smooth
    bool active;                  // 是否活跃（可交互）
    bool shine;                   // 是否发光
    RGBA color;                   // 绘制颜色
    Light light;                  // 光照信息
    BPnt _centroid;               // 永久质心
    BPnt centroid;                // 质心位置
    BMat4x4 modelMat;             // 模型矩阵（累计父节点）
    std::vector<BMat4x4> insMats; // 实例矩阵
    std::vector<BMat4x4> fixMats; // 修复矩阵
};

/**
 * @brief 前向声明
 *
 */
class Renderer;

/**
 * 交互基本类.
 */
class AIS_Base
{
    /**
     * @brief 声明 MNT 节点.
     * @see
     */
    CAGD_DECLARE_MNT(AIS_Base)

  public:
    /**
     * @brief 基本构造.
     * @param parent
     * @see
     */
    AIS_Base();

    /**
     * @brief 析构函数.
     * @see
     */
    virtual ~AIS_Base();

    /**
     * @brief 获得父节点对象.
     * @return
     * @see
     */
    AIS_Base *GetParent() const;

    /**
     * @brief 获得 type 类型的第 i 个子节点对象.
     * @return
     * @param type
     * @param i
     * @see
     */
    AIS_Base *GetChild(AIS_Type type, int i = 0) const;

    /**
     * @brief 添加父节点.
     * @param parent
     * @see
     */
    void AddParent(Handle(AIS_Base) parent);

    /**
     * @brief 移除父节点.
     * @see
     */
    void RemoveParent();

    /**
     * @brief 添加子节点.
     * @param child
     * @see
     */
    void AddChild(Handle(AIS_Base) child);

    /**
     * @brief 移除子节点.
     * @see
     */
    void RemoveChildren();

    /**
     * @brief 向父节点传递消息.
     * @param mess
     * @see
     */
    void PassMessageUp(Message mess);

    /**
     * @brief 向子节点传递消息.
     * @param mess
     * @see
     */
    void PassMessageDown(Message mess);

    /**
     * @brief 检测虚函数.
     * @return
     * @param pos
     * @see
     */
    virtual bool MoveTo(Point pos);

    /**
     * @brief 移动虚函数.
     * @param pos
     * @see
     */
    virtual bool Move(Point pos);

    /**
     * @brief 点击虚函数.
     * @return
     * @param pos
     * @see
     */
    virtual bool Click(Point pos);

    /**
     * @brief 释放虚函数.
     * @return
     * @param pos
     * @see
     */
    virtual bool Release(Point pos);

    /**
     * @brief 接收消息.
     * @param mess
     * @see
     */
    virtual void RecvMessage(Message mess);

    /**
     * @brief 刷新顶点数据.
     * @see
     */
    virtual void UpdateArray();

    /**
     * @brief 获得类型.
     * @return
     * @see
     */
    virtual AIS_Type GetType() const = 0;

    /**
     * @brief 刷新信息.
     * @return
     * @see
     */
    virtual void UpdateInfo() = 0;

    /**
     * @brief 获得信息.
     * @return
     * @see
     */
    AIS_Info &GetInfo();

    /**
     * @brief 更新深度.
     * @return
     * @see
     */
    bool UpdateDepth();

    /**
     * @brief 刷新 uniform 数据.
     * @see
     */
    void UpdateUniform();

    /**
     * @brief 设置深度.
     * @param depth
     * @see
     */
    void SetDepth(double depth);

    /**
     * @brief 活跃性传递给子节点.
     * @param active
     * @see
     */
    void SetActive(bool active);

    /**
     * @brief 注册渲染器.
     * @see
     */
    void RegisterRenderer(MainOpenGLWidget *parent);

    /**
     * @brief 绘制操作.
     * @see
     */
    void Draw();

  protected:
    AIS_Info m_info;
    AIS_Context &m_context;
    Handle(Renderer) m_renderer;
};

} // namespace CAGD
